/**
 * 
 */
package etric.mapmaker.gui;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import etric.mapmaker.base.OsmMapMaker;
import etric.mapmaker.output.GlopusKalFile;
import etric.mapmaker.output.OziMapFile;
import etric.mapmaker.output.TileMap;
import etric.mapmaker.tools.BoundingBox;
import etric.mapmaker.tools.CoordsConvert;

/**
 * Warning, there be dragons here....
 * 
 * big ones ....
 * 
 * 
 * really really big ....
 * @author etric
 */
public class GraphicalUserInterface extends JFrame implements GUI, ActionListener
{
	private static final long serialVersionUID = 1L;
	
	private OsmMapMaker app = null;
	
	private String wndTitelName = "OSM Map Maker";
	private Dimension wndSize   = new Dimension(400,400);
	
	private JTextField xValue = null;
	private JTextField yValue = null;
	private JTextField zValue = null;
	private JTextField gwValue = null;
	private JTextField nameValue = null;
	private JCheckBox Layer1 = null;
	private JCheckBox Layer2 = null;
	private JCheckBox Layer3 = null;
	private JCheckBox out1 = null;
	private JCheckBox out2 = null;
	private JCheckBox out3 = null;
	private JCheckBox out4 = null;
	private JTextArea console = null;

	public GraphicalUserInterface(OsmMapMaker app)
	{
		super();
		this.app = app;

		// create the window
		setTitle(wndTitelName);
		setSize(wndSize.width, wndSize.height);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocationRelativeTo(null);
		setResizable(true);
		
		//use GridBag Layout for the panel
		JPanel pane = new JPanel(new GridBagLayout());
		setContentPane(pane);
	}

	/* (non-Javadoc)
	 * @see etric.mapmaker.gui.GUI#run()
	 */
	public void run()
	{
		createPane();
		setVisible(true);
	}
	
	private void createPane()
	{
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.BOTH;
		
		c.gridx = 0;
		c.gridy = 0;
		c.gridheight = 2;
		c.weightx = 1;
		c.weighty = 1;
		getContentPane().add(createAreaPanel(), c);
		
		c.gridx = 1;
		c.gridy = 0;
		c.gridheight = 1;
		c.weightx = 0.5;
		c.weighty = 0.5;
		getContentPane().add(createLayerPanel(), c);
		
		c.gridx = 1;
		c.gridy = 1;
		c.gridheight = 1;
		getContentPane().add(createOutputPanel(), c);
		
		c.gridx = 0;
		c.gridy = 2;
		c.gridheight = 1;
		c.gridwidth = 2;
		c.weightx = 1;
		c.weighty = 1;
		getContentPane().add(createStatusPanel(), c);

	}
	
	private JPanel createAreaPanel()
	{
		TitledBorder titleBorder = BorderFactory.createTitledBorder("Area");
		
		JPanel panel = new JPanel(new GridBagLayout());
		panel.setBorder(titleBorder);
		

		JLabel titelLabel = new JLabel("Coordinates of the center tile.", JLabel.LEFT);
		xValue = new JTextField(5);
		JLabel xLabel = new JLabel("X:", JLabel.CENTER);
		yValue = new JTextField(5);
		JLabel yLabel = new JLabel("Y:", JLabel.CENTER);
		zValue = new JTextField(2);
		JLabel zLabel = new JLabel("Zoom:", JLabel.CENTER);
		gwValue = new JTextField(2);
		JLabel gwLabel = new JLabel("Gridwidth:", JLabel.CENTER);
		nameValue = new JTextField(20);
		JLabel nameLabel = new JLabel("Map Name: ", JLabel.CENTER);
		
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.HORIZONTAL;
		c.weightx = 1;
		c.weighty = 1;
		
		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 1;
		panel.add(nameLabel, c);
		
		c.gridx = 1;
		c.gridy = 0;
		c.gridwidth = 3;
		panel.add(nameValue, c);
		
		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 4;
		panel.add(titelLabel, c);
		
		c.gridx = 0;
		c.gridy = 2;
		c.gridwidth = 1;
		panel.add(xLabel, c);

		c.gridx = 1;
		c.gridy = 2;
		c.gridwidth = 3;
		panel.add(xValue, c);

		c.gridx = 0;
		c.gridy = 3;
		c.gridwidth = 1;
		panel.add(yLabel, c);

		c.gridx = 1;
		c.gridy = 3;
		c.gridwidth = 3;
		panel.add(yValue, c);

		c.gridx = 0;
		c.gridy = 4;
		c.gridwidth = 1;
		panel.add(zLabel, c);

		c.gridx = 1;
		c.gridy = 4;
		c.gridwidth = 1;
		panel.add(zValue, c);

		c.gridx = 2;
		c.gridy = 4;
		c.gridwidth = 1;
		panel.add(gwLabel, c);

		c.gridx = 3;
		c.gridy = 4;
		c.gridwidth = 1;
		panel.add(gwValue, c);

		return panel;
	}

	private JPanel createLayerPanel()
	{
		TitledBorder titleBorder = BorderFactory.createTitledBorder("Layers");
		
		JPanel panel = new JPanel(new GridBagLayout());
		panel.setBorder(titleBorder);
		
		//JLabel titelLabel = new JLabel("What layers should be used?.", JLabel.LEFT);
		Layer1 = new JCheckBox("Mapnik");
		Layer2 = new JCheckBox("Maplint");
		Layer3 = new JCheckBox("tiles@home");
		Layer3.setSelected(true);

		
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.NONE;
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 1;
		c.anchor = GridBagConstraints.LINE_START;
		
		//c.gridx = 0;
		//c.gridy = 0;
		//panel.add(titelLabel, c);

		c.gridx = 0;
		c.gridy = 0;
		panel.add(Layer1, c);

		c.gridx = 0;
		c.gridy = 1;
		panel.add(Layer2, c);

		c.gridx = 0;
		c.gridy = 2;
		panel.add(Layer3, c);
		
		return panel;
	}

	private JPanel createOutputPanel()
	{
		TitledBorder titleBorder = BorderFactory.createTitledBorder("Output");
		
		JPanel panel = new JPanel(new GridBagLayout());
		panel.setBorder(titleBorder);
		
		out1 = new JCheckBox("JPEG");
		out1.setSelected(true);
		out2 = new JCheckBox("PNG");
		out2.setSelected(true);
		out3 = new JCheckBox(".map File");
		out3.setSelected(true);
		out4 = new JCheckBox(".kal File");
		out4.setSelected(true);

		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.NONE;
		c.weightx = 1;
		c.weighty = 1;
		c.gridwidth = 1;
		c.anchor = GridBagConstraints.LINE_START;

		c.gridx = 0;
		c.gridy = 0;
		panel.add(out1, c);

		c.gridx = 0;
		c.gridy = 1;
		panel.add(out2, c);

		c.gridx = 0;
		c.gridy = 2;
		panel.add(out3, c);

		c.gridx = 0;
		c.gridy = 3;
		panel.add(out4, c);
		
		return panel;
	}
	
	private JPanel createStatusPanel()
	{
		TitledBorder titleBorder = BorderFactory.createTitledBorder("Status");
		
		JPanel panel = new JPanel(new GridBagLayout());
		panel.setBorder(titleBorder);
		
		JButton generate  = new JButton("Generate Map");
		generate.setActionCommand("generatemap");
		generate.addActionListener(this);
		JButton help  = new JButton("Help");
		help.setActionCommand("help");
		help.addActionListener(this);
		console = new JTextArea(5, 20);
		
		JScrollPane scrollPane = new JScrollPane(console,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		console.setEditable(false);

		GridBagConstraints c = new GridBagConstraints();
		c.gridwidth = 1;
		c.weighty = 0.5;

		c.gridx = 0;
		c.gridy = 0;
		panel.add(help, c);
		
		c.gridx = 0;
		c.gridy = 1;
		panel.add(generate, c);
		
		c.weightx = 1;
		c.weighty = 1;
		c.gridx = 1;
		c.gridy = 0;
		c.gridheight = 2;
		c.fill = GridBagConstraints.BOTH;
		panel.add(scrollPane, c);
		
		return panel;
	}
	
	private void generateMap()
	{
		
		int xCenter   = 0;
		int yCenter   = 0;
		int zoom      = 0;
		int gridWidth = 0;
		String mapName = null;
		
		// get values from input vields
		try {
			xCenter   = Integer.parseInt(xValue.getText());
			yCenter   = Integer.parseInt(yValue.getText());
			zoom      = Integer.parseInt(zValue.getText());
			gridWidth = Integer.parseInt(gwValue.getText());
			mapName = nameValue.getText();
			
		} catch (Exception errMessage)
		{
			JOptionPane.showMessageDialog(this, "Please insert correct values.","Some values are wrong.",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		
		if(mapName == null)
		{
			JOptionPane.showMessageDialog(this, "Please choose a mapname.","No mapname.",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		
		if(!(Layer1.isSelected() || Layer2.isSelected() || Layer3.isSelected()))
		{
			JOptionPane.showMessageDialog(this, "Please select at least one layer.","No layer selected.",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		
		if(!(out1.isSelected() || out2.isSelected() || out3.isSelected()))
		{
			JOptionPane.showMessageDialog(this, "Please select at least one output format.","No output selected.",
					JOptionPane.ERROR_MESSAGE);
			return;
		}
		
		console.append("creating bounding box ...\n");
		console.repaint();

		int gridShift = gridWidth/2;
		double pointN = CoordsConvert.convYtoLat(yCenter - gridShift, zoom);
		double pointS = CoordsConvert.convYtoLat(yCenter + gridShift+1, zoom);
		double pointE = CoordsConvert.convXtoLong(xCenter + gridShift+1, zoom);
		double pointW = CoordsConvert.convXtoLong(xCenter - gridShift, zoom);
		BoundingBox bb = new BoundingBox(pointN, pointE, pointS, pointW);
		
		OziMapFile calibrateOzi = new OziMapFile();
		GlopusKalFile calibrateGlopus = new GlopusKalFile();

		
		if(Layer1.isSelected())
		{
			TileMap td1 = new TileMap(mapName, TileMap.LAYER_MAPNIK);
			
			
			if(out1.isSelected() || out2.isSelected())
			{
				console.append("downloading tiles from " + Layer1.getText() + " layer ...\n");
				
				td1.getTiles(gridWidth, zoom, xCenter, yCenter);
			
				console.append("merge " + Layer1.getText() + " tiles ...\n");
				
				if(out1.isSelected() && out2.isSelected())
				{
					td1.mergeTiles(gridWidth, TileMap.OUTPUT_BOTH);
				}
				else if(out1.isSelected())
				{
					td1.mergeTiles(gridWidth, TileMap.OUTPUT_JPG);
				}
				else if(out2.isSelected())
				{
					td1.mergeTiles(gridWidth, TileMap.OUTPUT_PNG);
				}
			}
			
			console.append("create calibration file ...\n");

			if(out3.isSelected())
			{
				calibrateOzi.parseMapFile(app, td1.getMapTitel(),
						"map/" + td1.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256);
			}
			if(out4.isSelected() && out1.isSelected())
			{
				calibrateGlopus.parseMapFile(app, td1.getMapTitel(),
						"map/" + td1.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
				calibrateGlopus.parseMapFile(app, td1.getMapTitel(),
						"map/" + td1.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
			}
			if(out4.isSelected() && out2.isSelected())
			{
				calibrateGlopus.parseMapFile(app, td1.getMapTitel(),
						"map/" + td1.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
				calibrateGlopus.parseMapFile(app, td1.getMapTitel(),
						"map/" + td1.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "png");
			}
			
			td1.writeMapInfos(bb);

		}
		

		if(Layer2.isSelected())
		{
			TileMap td2 = new TileMap(mapName, TileMap.LAYER_MAPLINT);
			
			
			if(out1.isSelected() || out2.isSelected())
			{
				console.append("downloading tiles from " + Layer2.getText() + " layer ...\n");
				
				td2.getTiles(gridWidth, zoom, xCenter, yCenter);
			
				console.append("merge " + Layer1.getText() + " tiles ...\n");
				
				if(out1.isSelected() && out2.isSelected())
				{
					td2.mergeTiles(gridWidth, TileMap.OUTPUT_BOTH);
				}
				else if(out1.isSelected())
				{
					td2.mergeTiles(gridWidth, TileMap.OUTPUT_JPG);
				}
				else if(out2.isSelected())
				{
					td2.mergeTiles(gridWidth, TileMap.OUTPUT_PNG);
				}
			}
			
			console.append("create calibration file ...\n");
			
			if(out3.isSelected())
			{
				calibrateOzi.parseMapFile(app, td2.getMapTitel(),
						"map/" + td2.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256);
			}

			if(out4.isSelected() && out1.isSelected())
			{
				calibrateGlopus.parseMapFile(app, td2.getMapTitel(),
						"map/" + td2.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
				calibrateGlopus.parseMapFile(app, td2.getMapTitel(),
						"map/" + td2.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
			}
			if(out4.isSelected() && out2.isSelected())
			{
				calibrateGlopus.parseMapFile(app, td2.getMapTitel(),
						"map/" + td2.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
				calibrateGlopus.parseMapFile(app, td2.getMapTitel(),
						"map/" + td2.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "png");
			}
			
			td2.writeMapInfos(bb);
		}
		
		if(Layer3.isSelected())
		{
			TileMap td3 = new TileMap(mapName, TileMap.LAYER_TATHOME);
			
			if(out1.isSelected() || out2.isSelected())
			{
				console.append("downloading tiles from " + Layer3.getText() + " layer ...\n");
				
				td3.getTiles(gridWidth, zoom, xCenter, yCenter);
			
				console.append("merge " + Layer3.getText() + " tiles ...\n");
				
				if(out1.isSelected() && out2.isSelected())
				{
					td3.mergeTiles(gridWidth, TileMap.OUTPUT_BOTH);
				}
				else if(out1.isSelected())
				{
					td3.mergeTiles(gridWidth, TileMap.OUTPUT_JPG);
				}
				else if(out2.isSelected())
				{
					td3.mergeTiles(gridWidth, TileMap.OUTPUT_PNG);
				}
			}
			
			console.append("create calibration file ...\n");
			
			if(out3.isSelected())
			{
				calibrateOzi.parseMapFile(app, td3.getMapTitel(),
						"map/" + td3.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256);
			}

			if(out4.isSelected() && out1.isSelected())
			{
				calibrateGlopus.parseMapFile(app, td3.getMapTitel(),
						"map/" + td3.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
				calibrateGlopus.parseMapFile(app, td3.getMapTitel(),
						"map/" + td3.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
			}
			if(out4.isSelected() && out2.isSelected())
			{
				calibrateGlopus.parseMapFile(app, td3.getMapTitel(),
						"map/" + td3.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "jpg");
				calibrateGlopus.parseMapFile(app, td3.getMapTitel(),
						"map/" + td3.getMapTitel(),
						bb.getPointN(),
						bb.getPointS(),
						bb.getPointW(),
						bb.getPointE(),
						gridWidth*256, "png");
			}
			
			td3.writeMapInfos(bb);
		}


		console.append("finished ...\n");

	}
	
	/* (non-Javadoc)
	 * @see etric.mapmaker.gui.GUI#showErrorMessage(java.lang.String)
	 */
	public void showErrorMessage(String errMessage)
	{
		JOptionPane.showMessageDialog(this, errMessage,"Something strage happened!",
				JOptionPane.ERROR_MESSAGE);
	}
	
	/* (non-Javadoc)
	 * @see etric.mapmaker.gui.GUI#showErrorMessage(java.lang.String)
	 */
	public void showMessage(String Message)
	{
		console.append(Message + "\n");
	}
	
	/**
	 * Close the GUI and quits the programm
	 */
	public void quitApp()
	{
		dispose();
		setVisible(false);
		app.quitGame();
	}

	public void actionPerformed(ActionEvent e)
	{
		if ("generatemap".equals(e.getActionCommand()))
		{
			generateMap();
			System.out.println("muh");
        }
		else if ("help".equals(e.getActionCommand()))
		{
			String InfoText = "To create maps of your area from the existing tiles you just have to do some simple steps.\n\n1. Go to http://www.informationfreeway.org/\n2. Zoom to your area\n3. Right-click the image and save the image path\n4. Filename format is /zoom/x/y.png\n5. set a gridwidth (the result will be a square map with the size gridwidth * 256px)\n6. create the map\n\n I hope this small programm is a help for someone :)";
			JOptionPane.showMessageDialog(this, InfoText,"Help",
					JOptionPane.INFORMATION_MESSAGE);
        }
		
	}

}
